<template>
  <div
    :class="animate"
    :style="{ height: height, width: width, overflow: 'hidden' }"
    :id="chartOption.bindingDiv"
     ref="text"
  >
    <table :style="{ height: height, width: width, tableLayout: 'fixed' }">
      <thead :style="headTableStyle">
        <tr>
          <th :style="topheadStyle">排名</th>
          <th
            v-for="(item, index) in this.chartOption.cols"
            :key="index"
            :style="theadStyle(item)"
          >
            {{ item.title }}
          </th>
        </tr>
      </thead>
      <tbody
        :style="tbodyStyle"
        ref="tbody"
        @mouseenter="visible"
        @mouseleave="invisible"
      >
        <tr
          v-for="(item, index) in tableData"
          :key="index"
          :style="trStyle(index)"
          @click="clickRow(index)"
        >
          <td
            style="whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'"
            v-if="chartOption.showRank != false"
          >
            <span :style="spanStyle(index)">{{ index + 1 }}</span>
          </td>
          <td
            v-for="(col, colindex) in item"
            :key="colindex"
            :style="tdStyle(colindex)"
          >
            <a
              @click="fieldClick(col.field, col.value)"
              :style="linkStyle(col)"
              v-if="col.isBinding"
              >{{ col.value }}</a
            >
            <a style="cursor:default;" v-else>{{ col.value }}</a>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "@/views/dashboard/mixins/resize";
import VueEvent from "@/views/tool/datav/VueEvent";
import "../../animate/animate.css";
import { parseQueryString, fIsUrL } from "../../util/urlUtil";
import { bindChart } from "../../util/LinkageChart";
import { chartApiBar, remoteChartApi,chartBIanalysis  } from "@/api/tool/datav/chartApi";
import { tableBIanalysis } from "@/api/tool/datav/chartBI/chartTableBI";
import { getFormsource } from "@/api/tool/datav/formsource";
const animationDuration = 6000;
import { websocketCommand } from "../../util/websocket.js";

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart"
    },
    width: {
      type: String,
      default: "100%"
    },
    height: {
      type: String,
      default: "100%"
    },
    chartOption: {
      type: Object
    },
    drawingList: {
      type: Array
    }
  },
  data() {
    return {
      chart: null,

      dataOption: JSON.parse(JSON.stringify(this.chartOption)),
      tableData: [],
      key: 1,
      timer: "",
      wsObj: null,
      wsFlag: false,
      wsTimer: "",
      wsValue: null,
      animate: this.className,
      selectedRow: undefined
    };
  },
  watch: {
    width() {
      this.initChart();
    },
    height() {
      this.initChart();
    },
    chartOption: {
      deep: true,
      handler(newVal) {
        this.setOptions(JSON.parse(JSON.stringify(newVal)));
      }
    },
    "chartOption.timeout": {
      handler() {
        this.chart = null;
        this.initChart();
      }
    },
    "chartOption.dataSourceType": {
      handler(value) {
        //切换数据源重新连接
        if (value !== "websocket") {
          this.wsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
        if (value !== "url") {
          clearTimeout(this.timer);
        } 
      }
    },
    "chartOption.interfaceKey": {
      handler(newValue, oldValue) {
        //初始化不创建连接，改变接口地址重新创建
        if (oldValue !== undefined && oldValue != "") {
          this.wsValue = null;
          this.closeWs();
          this.createWs();
          this.animate = this.className;
        }
      }
    },
    wsFlag: {
      handler(value) {
        if (!value) {
          this.wsValue = null;
          this.closeWs();
        }
      }
    },
    className: {
      handler(value) {
        this.animate = value;
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart();
    });
    //setInterval(this.scrollTable, 2000);
  },
  beforeDestroy() {
    this.chart = null;
    clearTimeout(this.timer);
    if (this.wsFlag) {
      this.closeWs();
    }
  },
  computed: {
    headTableStyle() {
      let style = {};
      style.width = "100%";
      if (this.chartOption.isthead == false) {
        style.display = "none";
      }
      return style;
    },
    topheadStyle() {
      let style = {
        height: this.chartOption.theadheight + "px",
        backgroundColor: this.chartOption.theadbackgroundcolor,
        fontSize: this.chartOption.theadfontsize + "px",
        fontFamily: this.chartOption.theadfontfamily,
        color: this.chartOption.theadfontcolor,
        textAlign: this.chartOption.isLeft,
        verticalAlign: "middle"
      };
      if (this.chartOption.showRank == false) {
        style.display = "none";
      }
      return style;
    },
    theadStyle() {
      return function(item) {
        return {
          width: item.width + "%",
          height: this.chartOption.theadheight + "px",
          backgroundColor: this.chartOption.theadbackgroundcolor,
          fontSize: this.chartOption.theadfontsize + "px",
          fontFamily: this.chartOption.theadfontfamily,
          color: this.chartOption.theadfontcolor,
          textAlign: this.chartOption.isLeft,
          verticalAlign: "middle"
        };
      };
    },

    trStyle() {
      return function(index) {
        let style = {
          width: "100%",
          height: this.chartOption.tbodyheight + "px",
          tableLayout: "fixed",
          fontSize: this.chartOption.tbodyfontsize + "px",
          fontFamily: this.chartOption.tbodyfontfamily,
          color: this.chartOption.tbodyfontcolor,
          textAlign: this.chartOption.isLeft,
          verticalAlign: "middle",
          display: "inline-table"
        };
        //判断奇偶行设置不同颜色
        if (index % 2 != 0) {
          style.backgroundColor = this.chartOption.oddcolor;
        } else {
          style.backgroundColor = this.chartOption.evencolor;
        }
        if (
          index == this.selectedRow &&
          this.chartOption.selectedColor != null
        ) {
          style.backgroundColor = this.chartOption.selectedColor;
        }

        return style;
      };
    },
    spanStyle() {
      return function(index) {
        let topcolor = ["#ed405d", "#f78c44", "#49bcf7", "#878787"];
        let size = parseInt(this.chartOption.tbodyfontsize) + 6;
        let style = {
          width: size + "px",
          height: size + "px",
          borderRadius: "3px",
          color: "#fff",
          lineHeight: size + "px",
          textAlign: "ctenter",
          display: "inline-block"
        };
        if (index == 0) {
          style.backgroundColor = topcolor[0];
        } else if (index == 1) {
          style.backgroundColor = topcolor[1];
        } else if (index == 2) {
          style.backgroundColor = topcolor[2];
        } else {
          style.backgroundColor = topcolor[3];
        }
        return style;
      };
    },
    tbodyStyle() {
      let style = {
        height:
          this.height.replace("px", "") - this.chartOption.theadheight + "px",
        width: this.width,
        display: "block"
      };
      return style;
    }
  },
  methods: {
    initChart() {
      
      //判断是否开启定时器，当是访问url接口时候并且timeout不为0时候开启定时器
      if (this.timer != "") {
        clearTimeout(this.timer);
      }
      if (
        (this.chartOption.dataSourceType == 'url' || this.chartOption.dataSourceType == 'database') &&
        this.chartOption.timeout > 0
      ) {
        let timerTask = () => {
          this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
          this.timer = setTimeout(() => {
            timerTask();
          }, this.chartOption.timeout);
        };

        timerTask();
      }else{
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    setOptions: async function(dataOption) {
      //console.log("=>",dataOption)
      //初始化数据
      //如果不是静态数据就调用接口给staticDataValue赋值
      if (dataOption.dataSourceType == "url") {
        let paramJson = parseQueryString(dataOption.requestParameters);

        let interfaceURL = dataOption.interfaceURL;

        dataOption.staticDataValue = await chartApiBar(
          dataOption.requestMethod,
          interfaceURL,
          paramJson,
          dataOption.token
        );

        this.$set(
          this.dataOption,
          "staticDataValue",
          dataOption.staticDataValue
        );
      } else if (dataOption.dataSourceType == "database") {
        if (
          dataOption.database.executeSql != undefined &&
          dataOption.database.executeSql != ""
        ) {
          let result = [];
          if(dataOption.database.sqlType != 'custom'){
          
            result = await tableBIanalysis(dataOption.database);
          }else{
            result = await chartBIanalysis(dataOption.database);
          }
          if (result.code == 200) {
            dataOption.staticDataValue = result.data;
            this.$set(
              this.dataOption,
              "staticDataValue",
              dataOption.staticDataValue
            );
          } else {
            alert("操作数据库错误");
          }
        }
      } else if (dataOption.dataSourceType == "form") {
        if (dataOption.formSource != undefined) {
          let response = await getFormsource(dataOption.formSource.id);
          dataOption.staticDataValue = JSON.parse(response.data.formData);
          this.$set(
            this.dataOption,
            "staticDataValue",
            dataOption.staticDataValue
          );
        }
      } else if (dataOption.dataSourceType == "websocket") {
        if (
          dataOption.interfaceKey != undefined &&
          dataOption.interfaceKey != ""
        ) {
          if (!this.wsFlag) {
            this.wsFlag = true;
            this.wsValue = null;
            this.createWs();
          }
          if (this.wsValue != null) {
            dataOption.staticDataValue = this.wsValue;
          }
        }
      }

      this.key = Math.random();
      this.getTableData(dataOption.staticDataValue);
      //数据处理
       if(dataOption.customData != undefined && dataOption.customData != ""){
          
          try {
            this.$nextTick(() => {
              dataOption.staticDataValue = (
               //里面为要处理的代码块 
              eval(dataOption.customData) 
              
              )(
                dataOption.staticDataValue,
                this.$refs.text
              );
              this.getTableData(dataOption.staticDataValue);
            })
          } catch (error) {
            console.log(error)
          }
          
       }
       //交互组件配置
       if(dataOption.interactData != undefined && dataOption.interactData != ""){
          
          try {
            this.$nextTick(() => {
              dataOption.staticDataValue = (
               //里面为要处理的代码块 
              eval(dataOption.interactData) 
              
              )(
                dataOption.staticDataValue,
                this.$refs.text
              );
              this.getTableData(dataOption.staticDataValue);
            })
          } catch (error) {
            console.log(error)
          }
          
       }
     
    },

    tdStyle(colindex) {
      let cols = this.chartOption.cols;
      let style = {};
      if (cols.length > 0) {
        style.width = cols[colindex].width + "%";
      }
      //自动换行
      if (this.chartOption.wordWrap == "breakAll") {
        style.wordWrap = "break-word";
        style.wordBreak = "normal";
      }
      //自动隐藏
      else {
        style.whiteSpace = "nowrap";
        style.overflow = "hidden";
        style.textOverflow = "ellipsis";
      }
      return style;
    },
    getTableData(staticDataValue) {
      let tableData = [];
      //构建表格数据数组，判断是否满足动态列绑定列值，不满足设置空
      if (this.chartOption.cols.length > 0) {
        for (let staticValue of staticDataValue) {
          let trArr = [];

          for (let col of this.chartOption.cols) {
            let flag = false;
            for (let item in staticValue) {
              if (item == col.field) {
                let staticValueObj = {};
                staticValueObj.field = item;
                staticValueObj.value = staticValue[item];
                if (this.isBindingChart(item)) {
                  staticValueObj.isBinding = true;
                } else {
                  staticValueObj.isBinding = false;
                }
                //console.log(staticValueObj);
                trArr.push(staticValueObj);
                flag = true;
                break;
              }
            }
            if (flag == false) {
              let staticValueObj = {};
              staticValueObj.field = col.field;
              staticValueObj.value = "";
              trArr.push(staticValueObj);
            }
          }

          tableData.push(trArr);
        }
      }
      this.tableData = tableData;
    },
    visible: function() {
      if (
        this.height.replace("px", "") <
        this.chartOption.theadheight +
          this.chartOption.staticDataValue.length * this.chartOption.tbodyheight
      ) {
        let style = this.$refs.tbody.style;
        style.overflowY = "scroll";
      }
    },
    invisible: function() {
      let style = this.$refs.tbody.style;
      style.overflowY = "hidden";
    },
    isBindingChart(field) {
      let remoteTag = false;
      let linkTag = false;

      if (
        this.chartOption.isRemote == true &&
        this.chartOption.remoteCols != undefined
      ) {
        let remoteLinkTag = this.chartOption.remoteCols.filter(function(item) {
          return item.field == field;
        })[0];
        if (remoteLinkTag != null) {
          remoteTag = true;
        }
      }

      if (
        this.chartOption.isLink == true &&
        this.chartOption.linkageCols != undefined
      ) {
        let linkageTag = this.chartOption.linkageCols.filter(function(item) {
          return item.field == field;
        })[0];
        if (linkageTag != null) {
          linkTag = true;
        }
      } else if (
        this.chartOption.isDrillDown == true &&
        this.chartOption.drillCols != undefined
      ) {
        let drillTag = this.chartOption.drillCols.filter(function(item) {
          return item.field == field;
        })[0];
        if (drillTag != null) {
          linkTag = true;
        }
      }

      //远程控制标志以及联动标志同时为false则为false，否则为true
      if (remoteTag == false && linkTag == false) {
        return false;
      } else {
        return true;
      }
    },
    fieldClick(field, val) {
      //console.log(field,val);
      //获取联动图表
      if (this.chartOption.isLink == true) {
        let linkageTag = this.chartOption.linkageCols.filter(function(item) {
          return item.field == field;
        })[0];
        if (linkageTag != undefined) {
          let bindList = linkageTag.bindingChart;

          if (bindList.length > 0) {
            bindChart(linkageTag.paramName, val, bindList, this.drawingList);
          }
        }
      }
      //开启图表下钻
      else if (this.chartOption.isDrillDown == true) {
        //获取联动图表
        let drillTag = this.chartOption.drillCols.filter(function(item) {
          return item.field == field;
        })[0];
        if (drillTag != undefined && drillTag.bindingChart != "") {
          let num = 0;
          for (let i = 0; i < this.chartOption.drillCols.length; i++) {
            if (this.chartOption.drillCols[i].field == drillTag.field) {
              num = i;
            }
          }

          //获取绑定的图表
          let drillDownChartOption = drillTag.drillDownChartOption;

          drillDownChartOption.drillBgColor = drillTag.drillBgColor;

          if (
            drillDownChartOption != undefined &&
            drillDownChartOption != null
          ) {
            //判断是否有参数传递
            if (
              drillTag.paramName != null &&
              drillTag.paramName != "" &&
              drillTag.paramName != undefined
            ) {
              this.$set(
                this.chartOption.drillCols[num].drillDownChartOption
                  .chartOption,
                "requestParameters",
                drillTag.paramName + "=" + val
              );
              drillDownChartOption.chartOption.requestParameters =
                drillTag.paramName + "=" + val;
            } else {
              this.$set(
                this.chartOption.drillCols[num].drillDownChartOption
                  .chartOption,
                "requestParameters",
                ""
              );
              drillDownChartOption.chartOption.requestParameters = "";
            }
            //发送下钻消息
            VueEvent.$emit("drill_down_msg", drillDownChartOption);
          }
        }
      }
      //开启图表远程控制
      if (
        this.chartOption.isRemote == true &&
        this.chartOption.remoteCols.length > 0
      ) {
        //获取联动图表
        let remoteTag = this.chartOption.remoteCols.filter(function(item) {
          return item.field == field;
        })[0];

        if (
          remoteTag != undefined &&
          remoteTag.interfaceKey != undefined &&
          remoteTag.interfaceKey != ""
        ) {
          let remoteData = {};
          //创建ws接口地址数组
          let interfaceArr = new Array();
          let interfaceObj = {
            interfaceKey: remoteTag.interfaceKey,
            interfaceName: remoteTag.interfaceName,
            interfaceUrl: remoteTag.interfaceUrl
          };
          interfaceArr.push(interfaceObj);
          //ws接口参数
          remoteData.interface = interfaceArr;

          let queryObj = {};
          queryObj[remoteTag.field] = val;
          remoteData.query = queryObj;

          // //调用接口
          remoteChartApi(remoteData);
        }
      }
    },
    linkStyle(colItem) {
      if (this.chartOption.isLink == true) {
        //获取联动图表
        let linkageTag = this.chartOption.linkageCols.filter(function(item) {
          return item.field == colItem.field;
        })[0];

        if (linkageTag != undefined) {
          return { color: linkageTag.linkColor, cursor: "pointer" };
        }
      } else if (this.chartOption.isDrillDown == true) {
        //获取下钻图表
        let drillTag = this.chartOption.drillCols.filter(function(item) {
          return item.field == colItem.field;
        })[0];

        if (drillTag != undefined) {
          return { color: drillTag.linkColor, cursor: "pointer" };
        }
      }

      if (this.chartOption.isRemote == true) {
        //获取远程控制图表
        let remoteTag = this.chartOption.remoteCols.filter(function(item) {
          return item.field == colItem.field;
        })[0];

        if (remoteTag != undefined) {
          return { color: remoteTag.linkColor, cursor: "pointer" };
        }
      }
    },
    //  ws连接成功，后台返回的ws数据
    receiveMsg(e) {
      if (e.action == "chat") {
        // console.log('服务端推送',e);
        this.wsValue = JSON.parse(e.result);
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    createWs() {
      this.wsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(
        this.wsObj,
        "create",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
    },
    // 断网重连，需要处理的逻辑
    reconnectWs() {
      if (this.wsObj) {
        console.log("%c websocket_reconnect", "color:blue");
        this.createWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    sendHeartBeat() {
      if (this.wsTimer != "") {
        clearTimeout(this.wsTimer);
      }

      let wsTimerTask = () => {
        console.log("发送心跳", "ping");
        let obj = { action: "keep", key: this.chartOption.interfaceKey };
        this.wsObj.send(JSON.stringify(obj));
        this.wsTimer = setTimeout(() => {
          wsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.wsWarning();
      };

      wsTimerTask();
    },
    wsWarning() {
      //如果断开连接则显示组件警告动画并清除计数器
      if (this.wsObj.readyState == 3) {
        this.animate = "warning";
        clearTimeout(this.wsTimer);
      }
    },
    closeWs() {
      clearTimeout(this.wsTimer);
      websocketCommand(
        this.wsObj,
        "close",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
      this.wsObj = null;
    },
    clickRow(index) {
      if (index == this.selectedRow) {
        this.selectedRow = undefined;
      } else {
        this.selectedRow = index;
      }
    }
  }
};
</script>
<style ang="scss" scoped></style>
